<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h2>一、生命周期是什么</h2>
  <div>在Vue中实例从创建到销毁的过程就是生命周期，即指从创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程</div>
  <br>
  <div>PS：在Vue生命周期钩子会自动绑定 this 上下文到实例中，因此你可以访问数据，对 property 和方法进行运算。
    这意味着你不能使用箭头函数来定义一个生命周期方法</div>
  <h2>二、生命周期有哪些</h2>
  <div>Vue生命周期总共可以分为8个阶段</div>
  <ul>
    <li>beforeCreate:组件实例被创建之初</li>
    <li>created:组件实例已经完全创建</li>
    <li>beforeMount:组件挂载之前</li>
    <li>mounted:组件挂载到实例上去之后</li>
    <li>beforeUpdate:组件数据发生变化，更新之前</li>
    <li>updated:组件数据更新之后</li>
    <li>beforeDestroy:组件实例销毁之前</li>
    <li>destroyed:组件实例销毁之后</li>
    <li>activated:keep-alive 缓存的组件激活时</li>
    <li>deactivated:keep-alive 缓存的组件停用时调用</li>
    <li>errorCaptured:捕获一个来自子孙组件的错误时被调用</li>
  </ul>
  <h2>三、具体分析</h2>
  <h4>beforeCreate -> created</h4>
  <ul>
    <li>初始化vue实例，进行数据观测</li>
  </ul>
  <h4>created</h4>
  <ul>
    <li>完成数据观测，属性与方法的运算，watch、event事件回调的配置</li>
    <li>可调用methods中的方法，访问和修改data数据触发响应式渲染dom，可通过computed和watch完成数据计算</li>
    <li>此时vm.$el 并没有被创建</li>
  </ul>
  <h4>created -> beforeMount</h4>
  <ul>
    <li>判断是否存在el选项，若不存在则停止编译，直到调用vm.$mount(el)才会继续编译</li>
    <li>优先级：render > template > outerHTML</li>
    <li>vm.el获取到的是挂载DOM的</li>
  </ul>
  <h4>beforeMount</h4>
  <ul>
    <li>在此阶段可获取到vm.el</li>
    <li>此阶段vm.el虽已完成DOM初始化，但并未挂载在el选项上</li>
  </ul>
  <h4>beforeMount -> mounted</h4>
  <ul>
    <li>此阶段vm.el完成挂载，vm.$el生成的DOM替换了el选项所对应的DOM</li>
  </ul>
  <h4>mounted</h4>
  <ul>
    <li>vm.el已完成DOM的挂载与渲染，此刻打印vm.$el，发现之前的挂载点及内容已被替换成新的DOM</li>
  </ul>
  <h4>beforeUpdate</h4>
  <ul>
    <li>更新的数据必须是被渲染在模板上的（el、template、render之一）</li>
    <li>此时view层还未更新</li>
    <li>若在beforeUpdate中再次修改数据，不会再次触发更新方法</li>
  </ul>
  <h4>updated</h4>
  <ul>
    <li>完成view层的更新</li>
    <li>若在updated中再次修改数据，会再次触发更新方法（beforeUpdate、updated）</li>
  </ul>
  <h4>beforeDestroy</h4>
  <ul>
    <li>实例被销毁前调用，此时实例属性与方法仍可访问</li>
  </ul>
  <h4>destroyed</h4>
  <ul>
    <li>完全销毁一个实例。可清理它与其它实例的连接，解绑它的全部指令及事件监听器</li>
    <li>并不能清除DOM，仅仅销毁实例</li>
  </ul>
  <h2>四、使用场景分析</h2>
  <ul>
    <li>beforeCreate:执行时组件实例还未创建，通常用于插件开发中执行一些初始化任务</li>
    <li>created:组件初始化完毕，各种数据可以使用，常用于异步数据获取</li>
    <li>beforeMount:未执行渲染、更新，dom未创建</li>
    <li>mounted:初始化结束，dom已创建，可用于获取访问数据和dom元素</li>
    <li>beforeUpdate:更新前，可用于获取更新前各种状态</li>
    <li>updated:更新后，所有状态已是最新</li>
    <li>beforeDestroy:销毁前，可用于一些定时器或订阅的取消</li>
    <li>destroyed:组件已销毁，作用同上</li>
  </ul>
  <h2>五、题外话：数据请求在created和mouted的区别</h2>
  <div>created是在组件实例一旦创建完成的时候立刻调用，这时候页面dom节点并未生成</div>
  <br>
  <div>mounted是在页面dom节点渲染完毕之后就立刻执行的</div>
  <br>
  <div>触发时机上created是比mounted要更早的</div>
  <br>
  <div>两者相同点：都能拿到实例对象的属性和方法</div>
  <br>
  <div>讨论这个问题本质就是触发的时机，放在mounted请求有可能导致页面闪动（页面dom结构已经生成），但如果在页面加载前完成则不会出现此情况
    建议：放在create生命周期当中</div>
</body>
</html>